package edu.ccut.saturn.component;

import java.util.HashMap;
import java.util.Map;

/**
 * 定义验证规则的实现类。用户在对saturndata进行验证时可以通过配置参数来设置对字段及其验证逻辑的包涵和排除规则。
 * 参数的写法如下：key1[validateKey1,validateKey2],key2[validateKey1,validateKey2]
 * 提供了判断用户指定的key是否需要验证，及指定的key和指定的验证规则集合是否需要验证的方法。
 * <li>字段includeStr:记录了用户配置的包涵规则的字符串类型的参数值；
 * <li>字段excludeStr:记录了用户配置的排除规则的字符串类型的参数值；
 * <li>字段include:记录了包涵规则的内容，以map形式保存了包涵的key及验证规则键值的字符串数组；当用户没有配置包涵规则参数时字段值为空；
 * <li>字段exclude:记录了排除规则的内容，以map形式保存了包涵的key及验证规则键值的字符串数组；当用户没有配置排除规则参数时字段值为空；
 * 
 * @author 温建
 * 
 */
public class ValidateRule {

	private String includeStr;

	private String excludeStr;

	private Map<String, String[]> include;

	private Map<String, String[]> exclude;

	public ValidateRule(String includeStr, String excludeStr) {
		this.includeStr = includeStr;
		this.excludeStr = excludeStr;
		initIncludeMap();
		initExcludeMap();
	}

	private void initExcludeMap() {

		if (this.excludeStr != null && !"".equals(this.excludeStr)) {
			String[] excludes = this.excludeStr.split(",");

			if (excludes != null && excludes.length > 0) {
				this.exclude = new HashMap<String, String[]>();

				for (String excludeItem : excludes) {
					int index = excludeItem.indexOf("[");

					if (index > 0 && excludeItem.endsWith("]")) {
						String key = excludeItem.substring(0, index);
						String validateKeys = excludeItem.substring(index + 1,
								excludeItem.length() - 1);

						String[] value = null;

						if ("*".equals(validateKeys)) {
							value = new String[] { "*" };

						} else {
							value = validateKeys.split(",");
						}
						this.exclude.put(key, value);

					} else {
						this.exclude.put(excludeItem, new String[] { "*" });
					}
				}
			}
		}
	}

	private void initIncludeMap() {

		if (this.includeStr != null && !"".equals(this.includeStr)) {
			String[] includes = this.includeStr.split(",");

			if (includes != null && includes.length > 0) {
				this.include = new HashMap<String, String[]>();

				for (String includeItem : includes) {
					int index = includeItem.indexOf("[");

					if (index > 0 && includeItem.endsWith("]")) {
						String key = includeItem.substring(0, index);
						String validateKeys = includeItem.substring(index + 1,
								includeItem.length() - 1);

						String[] value = null;

						if ("*".equals(validateKeys)) {
							value = new String[] { "*" };

						} else {
							value = validateKeys.split(",");
						}
						this.include.put(key, value);

					} else {
						this.include.put(includeItem, new String[] { "*" });
					}
				}
			}
		}
	}

	/**
	 * 判断指定的key是否需要验证；
	 * 
	 * 
	 * @param key
	 * @return
	 */
	public boolean checkKeyNeedValidate(String key) {

		if (key != null && !"".equals(key)) {

			if (!((this.include != null && !this.include.containsKey(key)) || this.exclude != null
					&& this.exclude.containsKey(key)
					&& "*".equals(this.exclude.get(key)[0]))) {

				return true;
			}
		}
		return false;
	}

	/**
	 * 判断是否对某一属性使用某项验证规则进行验证。 只有当待验证的属性满足被包含并且没有排除的情况下才进行验证。排除的优先级高于包含。
	 * 首先判断指定的key是否需要验证，如果指定的key根本不需要验证，则返回false；否则判断指定的key的指定验证规则是否需要校验。
	 * 
	 * @param key
	 * @param validateKey
	 * @return true 表示指定key的指定规则需要进行校验；false表示指定key的指定规则不需要进行校验。
	 */
	public boolean isValidate(String key, String validateKey) {

		if (checkKeyNeedValidate(key) == false) {
			return false;
		}

		if (checkInclude(key, validateKey) && !checkExclude(key, validateKey)) {
			return true;
		}
		return false;
	}

	private boolean checkInclude(String key, String validateKey) {

		if (key != null && !"".equals(key)) {

			if (validateKey != null && !"".equals(validateKey)) {

				if (this.include == null) {
					return true;
				}

				if (this.include.keySet().contains(key)) {
					String[] validateKeys = this.include.get(key);

					if (validateKeys[0] != "*") {

						for (String item : validateKeys) {

							if (item.equals(validateKey)) {
								return true;
							}
						}
						return false;
					}
					return true;
				}
			}
		}
		return false;
	}

	private boolean checkExclude(String key, String validateKey) {

		if (key != null && !"".equals(key)) {

			if (validateKey != null && !"".equals(validateKey)) {

				if (this.exclude == null) {
					return false;
				}

				if (this.exclude.keySet().contains(key)) {
					String[] validateKeys = this.exclude.get(key);

					if (validateKeys[0] == "*") {
						return true;

					} else {

						for (String item : validateKeys) {

							if (item.equals(validateKey)) {
								return true;
							}
						}
						return false;
					}
				}
				return false;
			}
		}
		return true;
	}
}
